//
//
//

package notorious.rascal.variometer.model;

import notorious.rascal.variometer.*;
import java.util.ArrayList;
import android.util.Log;

public class KalmanFilteredVario implements DataSource {
    public static int KALMAN_VARIO = 1;
    public static int DAMPED_VARIO = 2;

    private double mVarDamp;

    public double mVar;
    public double mDampedVar;
    public double mLastVar;

    private int mVarType;

    private ArrayList<VarioChangeListener> mVarioChangeListeners;

    public double mMaxVarSinceLast = -1000.0;
    public double mMinVarSinceLast = 1000.0;
    public double mAvgVarSinceLast = 0.0;
    public int mCountSinceLast = 0;

    public KalmanFilteredAltitude mAltitude;

    public KalmanFilteredVario(KalmanFilteredAltitude altitude, double varDamp, int varType) {
        this.mAltitude = altitude;
        this.mVarDamp = varDamp;
        this.mVarType = varType;
    }

    public void setVarDamp(double varDamp) {
        this.mVarDamp = varDamp;
    }

    public void notifyListeners(double changedVar) {
        if (mVarioChangeListeners == null) {
            return;
        }
        for (int i = 0; i < mVarioChangeListeners.size(); i++) {
            mVarioChangeListeners.get(i).varioChanged(changedVar);

        }
    }

    public synchronized double getValue() {
        if (mVarType == DAMPED_VARIO) {
            return mDampedVar;
        }
        return mVar;
    }

    public synchronized void addChangeListener(VarioChangeListener varioChangeListener) {
        if (mVarioChangeListeners == null) {
            mVarioChangeListeners = new ArrayList<VarioChangeListener>();
        }
        
        mVarioChangeListeners.add(varioChangeListener);
    }

    public synchronized void removeChangeListener(VarioChangeListener varioChangeListener) {
        if (mVarioChangeListeners != null && mVarioChangeListeners.contains(varioChangeListener)) {
            mVarioChangeListeners.remove(varioChangeListener);
        }
    }

    public synchronized double[] getMinMaxAvgSinceLast() {
        double[] ret = null;
        if (mCountSinceLast > 0) {
            ret = new double[]{mMinVarSinceLast, mMaxVarSinceLast, mAvgVarSinceLast, mCountSinceLast};
        } else {
            ret = new double[]{0.0, 0.0, 0.0, 0.0};
        }
        
        mMaxVarSinceLast = -1000.0;
        mMinVarSinceLast = 1000.0;
        mAvgVarSinceLast = 0.0;
        mCountSinceLast = 0;
        
        return ret;
    }

    public synchronized double addData(double time) {
        mVar = mAltitude.getVarioValue();
        mDampedVar = mDampedVar + mVarDamp * (mVar - mDampedVar);

        if (mVarType == DAMPED_VARIO) {
            this.notifyListeners(mDampedVar);

            mLastVar = mDampedVar;

            if (mDampedVar > mMaxVarSinceLast) {
                mMaxVarSinceLast = mDampedVar;
            }
            if (mDampedVar < mMinVarSinceLast) {
                mMinVarSinceLast = mDampedVar;
            }
            
            mCountSinceLast++;
            mAvgVarSinceLast += (mDampedVar - mAvgVarSinceLast) / mCountSinceLast;
            
            return mDampedVar;

        } else {
        	//Log.i("Vario", "Vario = " + mVar);
            this.notifyListeners(mVar);

            mLastVar = mVar;

            if (mVar > mMaxVarSinceLast) {
                mMaxVarSinceLast = mVar;
            }
            if (mVar < mMinVarSinceLast) {
                mMinVarSinceLast = mVar;
            }
            
            mCountSinceLast++;
            mAvgVarSinceLast += (mVar - mAvgVarSinceLast) / mCountSinceLast;
            
            return mVar;
        }
    }
}
